ConvertGeodeticToTransverseMercator Subroutine

private subroutine ConvertGeodeticToTransverseMercator(lon, lat, k, centM, lat0, a, e, eb, falseN, falseE, x, y)

The subroutine converts geodetic(latitude and longitude) coordinates to Transverse Mercator projection (easting and northing) coordinates, according to the current ellipsoid and Transverse Mercator projection coordinates.

Arguments

Type IntentOptional Attributes Name
real(kind=float), intent(inout) :: lon

geodetic longitude [radians]

real(kind=float), intent(in) :: lat

geodetic latitude [radians]

real(kind=float), intent(in) :: k

scale factor

real(kind=float), intent(in) :: centM

central meridian [radians]

real(kind=float), intent(in) :: lat0

latitude of origin [radians]

real(kind=float), intent(in) :: a

semimajor axis [m]

real(kind=float), intent(in) :: e

eccentricity

real(kind=float), intent(in) :: eb

second eccentricity

real(kind=float), intent(in) :: falseN

false northing

real(kind=float), intent(in) :: falseE

false easting

real(kind=float), intent(out) :: x

easting coordinate [m]

real(kind=float), intent(out) :: y

northing coordinate [m]


Variables

Type Visibility Attributes Name Initial
real(kind=float), public, parameter :: MAX_DELTA_LONG = 90.*degToRad
real(kind=float), public, parameter :: MAX_LAT = 89.99*degToRad
real(kind=float), public :: c
real(kind=float), public :: c2
real(kind=float), public :: c3
real(kind=float), public :: c5
real(kind=float), public :: c7
real(kind=float), public :: dlam
real(kind=float), public :: ebs

second eccentricity squared

real(kind=float), public :: es

eccentricity squared

real(kind=float), public :: eta
real(kind=float), public :: eta2
real(kind=float), public :: eta3
real(kind=float), public :: eta4
real(kind=float), public :: s
real(kind=float), public :: sn
real(kind=float), public :: t
real(kind=float), public :: t1
real(kind=float), public :: t2
real(kind=float), public :: t3
real(kind=float), public :: t4
real(kind=float), public :: t5
real(kind=float), public :: t6
real(kind=float), public :: t7
real(kind=float), public :: t8
real(kind=float), public :: t9
real(kind=float), public :: tan2
real(kind=float), public :: tan3
real(kind=float), public :: tan4
real(kind=float), public :: tan5
real(kind=float), public :: tan6
real(kind=float), public :: temp_Long
real(kind=float), public :: temp_Origin
real(kind=float), public :: tmd
real(kind=float), public :: tmdo

Source Code

SUBROUTINE ConvertGeodeticToTransverseMercator &
!
(lon, lat, k, centM, lat0, a, e, eb, falseN, falseE, x, y)

USE Units, ONLY: &
!Imported parametes:
pi

USE StringManipulation, ONLY: &
!Imported routines:
ToString

IMPLICIT NONE

! Arguments with intent(in):
REAL (KIND = float), INTENT (INOUT) :: lon !!geodetic longitude [radians]
REAL (KIND = float), INTENT (IN) :: lat !!geodetic latitude [radians]
REAL (KIND = float), INTENT (IN) :: k !!scale factor
REAL (KIND = float), INTENT (IN) :: centM !!central meridian [radians]
REAL (KIND = float), INTENT (IN) :: lat0 !!latitude of origin [radians]
REAL (KIND = float), INTENT (IN) :: a !! semimajor axis [m]
REAL (KIND = float), INTENT (IN) :: e !! eccentricity
REAL (KIND = float), INTENT (IN) :: eb !! second eccentricity
REAL (KIND = float), INTENT (IN) :: falseN !!false northing
REAL (KIND = float), INTENT (IN) :: falseE !!false easting



!Arguments with intent(out):
REAL (KIND = float), INTENT (OUT) :: x !!easting coordinate [m]
REAL (KIND = float), INTENT (OUT) :: y !!northing coordinate [m]

!Local variables:
REAL (KIND = float) :: c !Cosine of latitude
REAL (KIND = float) :: c2
REAL (KIND = float) :: c3
REAL (KIND = float) :: c5
REAL (KIND = float) :: c7
REAL (KIND = float) :: es !!eccentricity squared
REAL (KIND = float) :: ebs !!second eccentricity squared
REAL (KIND = float) :: dlam  !Delta longitude - Difference in Longitude
REAL (KIND = float) :: eta !constant - TranMerc_ebs *c *c
REAL (KIND = float) :: eta2
REAL (KIND = float) :: eta3
REAL (KIND = float) :: eta4
REAL (KIND = float) :: s !Sine of latitude
REAL (KIND = float) :: sn !Radius of curvature in the prime vertical
REAL (KIND = float) :: t !Tangent of latitude
REAL (KIND = float) :: tan2
REAL (KIND = float) :: tan3
REAL (KIND = float) :: tan4
REAL (KIND = float) :: tan5
REAL (KIND = float) :: tan6
REAL (KIND = float) :: t1 !Term in coordinate conversion formula
REAL (KIND = float) :: t2 !Term in coordinate conversion formula
REAL (KIND = float) :: t3 !Term in coordinate conversion formula
REAL (KIND = float) :: t4 !Term in coordinate conversion formula
REAL (KIND = float) :: t5 !Term in coordinate conversion formula
REAL (KIND = float) :: t6 !Term in coordinate conversion formula
REAL (KIND = float) :: t7 !Term in coordinate conversion formula
REAL (KIND = float) :: t8 !Term in coordinate conversion formula
REAL (KIND = float) :: t9 !Term in coordinate conversion formula
REAL (KIND = float) :: tmd !True Meridional distance
REAL (KIND = float) :: tmdo !True Meridional distance for latitude of origin
REAL (KIND = float) :: temp_Origin
REAL (KIND = float) :: temp_Long

! Local parameters:
REAL (KIND = float), PARAMETER :: MAX_LAT = 89.99 * degToRad    ! 89.99 degrees in radians
REAL (KIND = float), PARAMETER :: MAX_DELTA_LONG =  90. * degToRad    ! 90. degrees in radians

!------------end of declaration------------------------------------------------

IF ( lat < -MAX_LAT .OR. lat > MAX_LAT ) THEN
  CALL Catch ('error', 'GeoLib',   &
    'Converting Geodetic to Transverse Mercator: &
    latitude out of range' ,  &
    code = consistencyError, argument = ToString(lat*radToDeg)//' deg' )
END IF
  
IF ( lon > pi) THEN
   lon = lon - 2*pi
END IF

 IF ( lon < centM - MAX_DELTA_LONG .OR. lon > centM + MAX_DELTA_LONG ) THEN
    IF ( lon < 0. ) THEN
      temp_Long = lon + 2 * pi
    ELSE
      temp_Long = lon
    END IF
    
    IF ( centM < 0. ) THEN
      temp_Origin = centM + 2 * pi
    ELSE
      temp_Origin = centM
    END IF
    
    IF ( temp_Long < temp_Origin - MAX_DELTA_LONG .OR. &
         temp_Long > temp_Origin + MAX_DELTA_LONG   ) THEN
        CALL Catch ('error', 'GeoLib',   &
         'Converting Geodetic to Transverse Mercator: &
         longitude out of range' ,  &
         code = consistencyError, argument = ToString(lon*radToDeg)//' deg' ) 
    END IF
    
 END IF
 
 !Delta longitude
 dlam = lon - centM
 
 ! Check for distortion and send warning.
!Distortion will result if Longitude is more than 9 degrees 
!from the Central Meridian at the equator
!and decreases to 0 degrees at the poles
!As you move towards the poles, distortion will become more significant 
IF ( ABS(dlam) > (9.0 * degToRad) * COS(lat) ) THEN
   CALL Catch ('warning', 'GeoLib',   &
     'Converting Geodetic to Transverse Mercator: &
     possible distortion in longitude computation ' ,  &
      argument = ToString(lon*radToDeg)//' deg' ) 
END IF

IF ( dlam > pi ) THEN
  dlam = dlam - (2 * pi)
END IF

IF ( dlam < -pi ) THEN
  dlam = dlam + (2 * pi)
END IF

IF ( ABS(dlam) < 2.e-10 ) THEN
  dlam = 0.0
END IF

!Eccentricities squared
es = e**2.
ebs = eb**2.

! Sine Cosine terms
s = SIN (lat)
c = COS (lat)
c2 = c * c
c3 = c2 * c
c5 = c3 * c2
c7 = c5 * c2

! Tangent Value
t = TAN (lat)
tan2 = t * t
tan3 = tan2 * t
tan4 = tan3 * t
tan5 = tan4 * t
tan6 = tan5 * t
eta = ebs * c2
eta2 = eta * eta
eta3 = eta2 * eta
eta4 = eta3 * eta

! Radius of curvature in the prime vertical
sn = Nu (lat, a, e)

!True Meridianal Distances 
tmd = MeridionalDistance (lat, a, e)  

! True Meridional Distance for latitude of origin 
tmdo = MeridionalDistance (lat0, a, e)

!northing 
t1 = (tmd - tmdo) * k
t2 = sn * s * c * k/ 2.e0
t3 = sn * s * c3 * k * (5.e0 - tan2 + 9.e0 * eta + 4.e0 * eta2) /24.e0
t4 = sn * s * c5 * k * (61.e0 - 58.e0 * tan2                     &
     + tan4 + 270.e0 * eta - 330.e0 * tan2 * eta + 445.e0 * eta2 &
     + 324.e0 * eta3 -680.e0 * tan2 * eta2 + 88.e0 * eta4        &
     -600.e0 * tan2 * eta3 - 192.e0 * tan2 * eta4) / 720.e0

t5 = sn * s * c7 * k * (1385.e0 - 3111.e0 * &
     tan2 + 543.e0 * tan4 - tan6) / 40320.e0

y = falseN + t1 + dlam**2. * t2 + dlam**4. * t3 + dlam**6. * t4 + dlam**8. * t5

!Easting 
t6 = sn * c * k
t7 = sn * c3 * k * (1.e0 - tan2 + eta ) / 6.e0
t8 = sn * c5 * k * (5.e0 - 18.e0 * tan2 + tan4                       &
     + 14.e0 * eta - 58.e0 * tan2 * eta + 13.e0 * eta2 + 4.e0 * eta3 &
     - 64.e0 * tan2 * eta2 - 24.e0 * tan2 * eta3 ) / 120.e0
t9 = sn * c7 * k * ( 61.e0 - 479.e0 * tan2 &
     + 179.e0 * tan4 - tan6 ) / 5040.e0

x = falseE + dlam * t6 + dlam**3. * t7 + dlam**5 * t8 + dlam**7. * t9 

END SUBROUTINE ConvertGeodeticToTransverseMercator